﻿using System;
using Pagination.Storage;
using Pagination.Tokenizer;

namespace Pagination
{
    public class Paginator : IPaginator
    {
        public virtual void Paginate(ITokenizer tokenizer, IStorage storage)
        {
            InitialAdd(tokenizer, storage);
            ExecuteCommands(tokenizer, storage);
        }

        private static void ExecuteCommands(ITokenizer tokenizer, IStorage storage)
        {
            var count = TryReadInt(tokenizer);
            for(var i  = 0; i < count; ++i)
            {
                var command = tokenizer.Next();
                if (command == "+")
                    ExecuteAdd(tokenizer, storage);
                else if (command == "?")
                    ExecuteRange(tokenizer, storage);
                else
                    throw new Exception("Expected command (+, ?), but was <" + command + ">");
            }
        }

        private static void ExecuteRange(ITokenizer tokenizer, IStorage storage)
        {
            var from = TryReadInt(tokenizer);
            var to = TryReadInt(tokenizer);
            storage.Range(from, to);
        }

        private static void ExecuteAdd(ITokenizer tokenizer, IStorage storage)
        {
            storage.Add(TryReadInt(tokenizer));
        }


        private static void InitialAdd(ITokenizer tokenizer, IStorage storage)
        {
            var count = TryReadInt(tokenizer);
            for(var i = 0; i < count; ++i)
                ExecuteAdd(tokenizer, storage);
        }

        private static int TryReadInt(ITokenizer tokenizer)
        {
            var token = tokenizer.Next();
            try
            {
                return int.Parse(token);
            }
            catch(FormatException e)
            {
                throw new Exception("Expected int, but was <" + token + ">" ,e);
            }
        }

    }
}
